package astroH;



/**
 *
 * @author ajh
 */
public class Astro {
    
    static double ONE_HALF_PI = Math.PI / 2;
    
    static public double toJulian(double year, double month, double day) {
        if (month <= 2) {
            year = year - 1;
            month = month + 12;
        }   
        int a = (int)(year / 100);
        int b = 2 - a + (int)(a/4);
        double jd = (int)(365.25 * (year + 4716.0)) + 
                (int)(30.6001 * (month + 1.0)) + day + b - 1524.5;
        return jd;
    }
    
    /**
        Returns the arcsine of the specified value.
    */
    public static final double asin(double fx) {
        if (Math.abs(fx) > 1) {
            throw new ArithmeticException("NaN");
        }
        else if (Math.abs(fx - 1.0) < 0.00000001) { // one-ish
            return ONE_HALF_PI;
        }
        else if (fx == -1.0) {
            return -ONE_HALF_PI;
        }
        else {
            return atan(fx/Math.sqrt(1.0 - (fx * fx)));
        }
    }


    /**
        Returns the arccosine of the specified value.
    */
    public static final double acos(double fx) {
        return ONE_HALF_PI - asin(fx);
    }

    /**
    Returns the arctangent of the specified value.
    */
    public static final double atan(double fx) {
        boolean negative = false;
        boolean invert = false;
        if (Math.abs(fx - 1.0) < 0.00000001) { // one-ish
            return 0;
        }
        if (fx < 0) {
            negative = true;
            fx = -fx;
        }

        // Avoid overflow
        if (fx > 1.0) {
            invert = true;
            fx = 1.0 / fx;
        }

        // Approximation from Ranko at http://www.lightsoft.co.uk/PD/stu/stuchat37.html
        // r(x) = (x + 0.43157974*x^3)/(1 + 0.76443945*x^2 + 0.05831938*x^4)
        double fxPow2 = fx * fx;
        double fxPow3 = fxPow2 * fx;
        double fxPow4 = fxPow3 * fx;
        double numer = fx + 0.43157974 * fxPow3;
        double denom = 1.0 + (0.76443945 * fxPow2) + (0.05831938 * fxPow4);
        double answer = numer / denom;

        if (invert) {
            answer = ONE_HALF_PI - answer;
        }
        if (negative) {
            answer = -answer;
        }
        return answer;
    }
}
